 
import { ABaseDecision } from "GameLoop/DecisionMaking/BaseDecision";
import { MainStrategy } from "GameLoop/WorldState/EntityManager/CreateStrategy/MainStrategy";
import { getRoleConfig } from "utils/constants/bodyconstant";
import { priority } from "utils/constants/definetypes";
import { config_rampart_hits, rampart_max_hits, repair_addition } from "utils/constants/globalconstant";
import { BodyEfficiency } from "utils/creep/bodyEfficiency";
import { TaskHelper } from "utils/task/TaskHelper";

/**
 * 维修ram决策
 */
export class RampartRepairDecision< T extends "creep" ="creep" > extends ABaseDecision<T>
{
   
    public isExpired(event: NormalEvent, region: string): boolean 
    {
       
        const room = Game.rooms[event.region];
        if(room.getEntity("CoreEntity").resourceCount(RESOURCE_ENERGY)<20000)
        {
            return false;
        }

        return true;
    }
    public makeTask(event: NormalEvent, region: string): IDecisionCode<T>|false
    {
        //  只有自己的房间才能修ram
        const lordroom = Game.rooms[event.region] as Required<Room>;
     
        const structcache = this.WorldGetter.Station.PollStructure(event.room);

        if(!structcache)
        {
            return false;
        }
        const repairgoal = this.getRepairGoal(lordroom);
        if(!repairgoal || repairgoal.repairArray.length==0)
        {
            return false;
        }
        
        let repair_sum = _.sum(repairgoal.repairArray,e=>e[1]-Game.getObjectById(e[0])!.hits);
        const body = getRoleConfig("worker",lordroom.controller.level);
        const worker_count = Math.min( BodyEfficiency.calCreepCountByProgress(repair_sum,body.body,"repair"),10);
        let worknunm = Math.max(1,worker_count);
        if(!lordroom.isSafe())
        {
            worknunm+=2;
        }
        let taskid =  `${event.room}_creep_repair_ram`;
        let task = lordroom.findTaskById<ITask<ICreepTaskData<"repair">>>(taskid,"creep")  
        if(task)
        {
            task.data.arg.targets = repairgoal.repairArray;
            task.data.required=[
                [['worker'],worknunm,worknunm]
            ]
            return false;
        }
        const repairTask:ICreepTaskData<"repair"> = 
        {
            type:"repair",
            arg:{
                room:lordroom.name,
                targets:repairgoal.repairArray
            },
            room:lordroom.name,
            creeps:[],
            body:{},
            income:-1,
            cost:TaskHelper.getTaskPathCost(event.region,event.room),
            required:[
                [['worker'],worknunm,worknunm]
            ]
        }
         // 根据升级共数量。计算运输工数量
        const code:IDecisionCode<T>={
            region:event.region,
            isunique:false,
            task:[{
                id:`${event.room}_creep_repair_ram`,
                ttl:-1,
                priority:priority.D,
                type:"creep",
                data:repairTask,
                shard:Math.max(1,worker_count),
            } as any],
        }
        return code
        
        // return false;
    }
    

    private getRepairGoal(room:Room)
    {
        const structcache = this.WorldGetter.Station.PollStructure(room.name);

        if(!structcache)
        {
            return false;
        }
        const structures = structcache.getStructure(STRUCTURE_RAMPART);
        if(structures)
        {
            let tmp_hitgoal = Math.min(  config_rampart_hits[room.controller?.level as number]/10,rampart_max_hits);
            const curMaxHits = Game.shard.name== "shard3"?tmp_hitgoal*0.5:tmp_hitgoal;
            const ramparts:StructureRampart[] = [];
            structures.forEach(e=>
                {
                    const s = Game.getObjectById(e.id);
                    if(s && s.hits<curMaxHits && s.hits<s.hitsMax)
                    {
                        ramparts.push(s);
                    }
                });
            if(ramparts.length == 0)
            {
                return false;
            }
            const min_hits = _.min(ramparts,e=>e.hits);
            let goal_hit=50000; 
            if(min_hits.hits<10000)
            {
                goal_hit = 50000
            }
            else  if(min_hits.hits<2000)
            {
                goal_hit = 10000
            }
            else 
            {
                goal_hit = Math.min( repair_addition*(1+Math.ceil(min_hits.hits/repair_addition)),curMaxHits+repair_addition);
            }
            // 维修目标
            const repairtarget:Record<string,number>={};
            const goalArray:[Id<Structure>,number][]=[];
            for(const e of ramparts)
            {
                if(e.hits<goal_hit)
                {
                    repairtarget[e.id]=goal_hit;
                    goalArray.push([e.id,goal_hit]);
                }
            }
            return {repair:repairtarget,repairArray:goalArray}
            
        }
        return false;
    }
}